/*
 * ModelCC, distributed under ModelCC Shared Software License, www.modelcc.org
 */

package org.modelcc.language.syntax.builder;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.util.logging.Level;

import org.modelcc.io.java.Reflection;
import org.modelcc.language.factory.SymbolIdentifier;
import org.modelcc.language.metamodel.SimpleLanguageElement;
import org.modelcc.language.metamodel.LanguageModel;
import org.modelcc.language.syntax.ParserMetadata;
import org.modelcc.language.syntax.Symbol;
import org.modelcc.language.syntax.SymbolBuilder;

import test.modelcc.language.types.model.ObjectCaster;

/**
 * Empty symbol builder
 * 
 * @author Luis Quesada (lquesada@modelcc.org) & Fernando Berzal (fberzal@modelcc.org)
*/
public final class EmptySymbolBuilder extends SymbolBuilder implements Serializable 
{
    /**
     * Constructor.
     */
    public EmptySymbolBuilder(LanguageModel model) 
    {
    	super(model);
    }
    
    /**
     * Builds a empty symbol, filling its data, and validates it.
     * @param t empty symbol to be built.
     * @return true if the empty symbol is valid, false if not
     */
    @Override
	public boolean build(Symbol t, ParserMetadata data) 
    {
    	SymbolIdentifier eid = (SymbolIdentifier)t.getType();
        SimpleLanguageElement be = (SimpleLanguageElement) eid.getElement();
        Class c = be.getElementClass();
        boolean valid = true;
        Object o;
        try {
            o = c.newInstance();

            if (be.getValueField() != null) {
            	Field fld = Reflection.findField(c,be.getValueField());
                if (fld != null) {
                    fld.setAccessible(true);
                    String str = null;
                    if (t.getInputSymbol().getString() != null)
                    	str = t.getInputSymbol().getString();
                    if (str == null)
                    	str = "";
                    fld.set(o, ObjectCaster.cast(fld.getType(),str));
                }
            }
            runSetupMethods(o,be);
            valid &= runConstraints(o,be);
            t.setUserData(o);

        } catch (Exception ex) {
            log(Level.SEVERE, null, ex);
            return false;
        }

        return valid;
    }


}
